#pragma once 
#include <memory>
#include <functional>
#include "fields.hpp"

namespace yjz_rpc
{
    class BaseMessage
    {
    public:
        using ptr = std::shared_ptr<BaseMessage>;
        virtual ~BaseMessage(){}
        virtual void setId(const std::string& id) { _id = id; }
        virtual std::string getId() { return _id; }
        virtual void setMType(MType mtype) { _mtype = mtype; }
        virtual MType getMType() { return _mtype; }
        virtual std::string serialize() = 0;
        virtual bool unserialize(const std::string& msg) = 0;
        virtual bool check() = 0;
    protected:
        std::string _id;
        MType _mtype;
    };

    class BaseBuffer
    {
    public:
        using ptr = std::shared_ptr<BaseBuffer>;
        virtual size_t readableSize() = 0;
        virtual int32_t peekInt32() = 0;                        // 尝试取出4字节不删除
        virtual void retrieveInt32() = 0;                       // 删除缓冲区中前4字节
        virtual int32_t readInt32() = 0;                           // 取出4字节并删除
        virtual std::string retrieveAsString(size_t len) = 0;   // 取出指定长度数据
    };

    class BaseProtocol
    {
    public:
        using ptr = std::shared_ptr<BaseProtocol>;
        virtual bool canProcessed(const BaseBuffer::ptr& buf) = 0;
        virtual bool onMessage(const BaseBuffer::ptr& buf, BaseMessage::ptr& msg) = 0;
        virtual std::string serialize(const BaseMessage::ptr& msg) = 0;
    };

    class BaseConnection
    {
    public:
        using ptr = std::shared_ptr<BaseConnection>;
        virtual void send(const BaseMessage::ptr& msg) = 0;
        virtual void shutdown() = 0;
        virtual bool connected() = 0;
    };

    using ConnectionCallBack = std::function<void(const BaseConnection::ptr&)>;
    using CloseCallBack = std::function<void(const BaseConnection::ptr&)>;
    using MessageCallBack = std::function<void(const BaseConnection::ptr&, BaseMessage::ptr&)>;

    class BaseServer
    {
    public:
        using ptr = std::shared_ptr<BaseServer>;
        virtual void setConnectionCallBack(const ConnectionCallBack& connection)
        {
            _connection = connection;
        }
        virtual void setCloseCallBack(const CloseCallBack& close)
        {
            _close = close;
        }
        virtual void setMessageCallBack(const MessageCallBack& message)
        {
            _message = message;
        }
        virtual void start() = 0;
    protected:
        ConnectionCallBack _connection;
        CloseCallBack _close;
        MessageCallBack _message;
    };

    class BaseClient
    {
    public:
        using ptr = std::shared_ptr<BaseClient>;
        virtual void setConnectionCallBack(const ConnectionCallBack& connection)
        {
            _connection = connection;
        }
        virtual void setCloseCallBack(const CloseCallBack& close)
        {
            _close = close;
        }
        virtual void setMessageCallBack(const MessageCallBack& message)
        {
            _message = message;
        }
        virtual void connect() = 0;
        virtual void shutdown() = 0;
        virtual bool send(const BaseMessage::ptr& msg) = 0;
        virtual BaseConnection::ptr getConnect() = 0;
        virtual bool connected() = 0;
    protected:
        ConnectionCallBack _connection;
        CloseCallBack _close;
        MessageCallBack _message;
    };
}